home *** CD-ROM | disk | FTP | other *** search
- /******************************************************************************
-
- MODUL
- $Id: command.c 1.3 1994/09/09 12:31:30 digulla Exp digulla $
-
- HISTORY
- 06. Dec 1992 ada created
- $Log: command.c $
- * Revision 1.3 1994/09/09 12:31:30 digulla
- * added new style Prototypes, DEFCMD and DEFHELP
- *
- * Revision 1.2 1994/08/19 14:08:50 digulla
- * added new commands by B. Noll
- *
- * Revision 1.1 1994/08/13 16:35:34 digulla
- * Initial revision
- *
-
- ******************************************************************************/
-
- /**************************************
- Includes
- **************************************/
- #include "defs.h"
-
-
- /**************************************
- Globale Variable
- **************************************/
- extern int foundcmd; /* control for implicit ARexx macro invocation */
- extern int cmderr; /* global command error flag for do_rexx()'s use */
-
-
- /**************************************
- Interne Defines & Strukturen
- **************************************/
- #define CF_COK 1 /* Can be executed while in command line mode */
- #define CF_PAR 2 /* ESCIMM special flag.. save rest of command line */
- /* so it can be executed after user entry */
- #define CF_ICO 4 /* OK to execute if iconified, else uniconify first*/
- #define CF_VWM 8 /* OK to execute if in viewmode, else abort */
- #define CF_BLK 16 /* needs Block */
-
- #define BTOCP(val, type) ((type)((long)val << 2))
-
- typedef void (*FPTR)(long);
-
- typedef struct
- {
- const char * name; /* command name */
- UBYTE args; /* number of arguments */
- UBYTE flags; /* flags */
- FPTR func; /* c-function */
- } COMM;
-
- #define MAXIA 5
-
-
- /**************************************
- Interne Variable
- **************************************/
-
- static CONST COMM Comm[] =
- {
- #undef DEFUSERCMD
- #define DEFUSERCMD(str,nargs,flags,ret,func,param,ext) str, nargs, flags, (FPTR) func,
- #include "commands.h"
- #undef DEFUSERCMD
- #define DEFUSERCMD(str,nargs,flags,ret,func,param,ext) ret func param ext
- };
-
-
- static CONST COMM repcmd =
- {
- "repeat", 2, CF_COK|CF_ICO, (FPTR)do_repeat,
- };
-
-
- /**************************************
- Interne Prototypes
- **************************************/
-
-
- Prototype int do_command (char * str);
-
- int do_command (char * str)
- {
- char * arg;
- char * aux1,
- * aux2,
- * repstr[MAXIA];
- char quoted;
- WORD repi = 0;
- long j;
- WORD low;
- WORD high;
- WORD diff;
- static int level = 0;
- COMM * comm;
- #define DEBUG_FILE /* Logging on ? */
- #ifdef DEBUG_FILE
- static FILE * debug_file = NULL;
-
- if (!debug_file && GETF_DEBUG(Ep))
- debug_file = fopen ("t:XDME.debug", "w");
- #endif
-
- if (!str || !*str)
- return (1);
-
- #ifdef DEBUG_FILE
- if (debug_file && GETF_DEBUG(Ep))
- fprintf (debug_file, "%s\n", str);
- #endif
-
- if (GETF_DEBUG(Ep)) printf("dcom[%2d|%d]: %s\n", level+1, GETF_ABORTCOMMAND(Ep), str);
-
- if (MacroRecord != 0 && level == 0) { /* PATCH_NULL [14 Feb 1993] : added */
- add_record (str); /* PATCH_NULL [14 Feb 1993] : added */
- } /* if */ /* PATCH_NULL [14 Feb 1993] : added */
-
- if (++level > 20)
- {
- DEFMESSAGE( _COM_recursion_too_deep, "command:\nRecursion too deep" )
- error (_COM_recursion_too_deep);
- --level;
-
- foundcmd = 1; /* to prevent us from trying an ARexx macro */
-
- return (0);
- }
-
- while ((arg = breakout (&str, "ed, &aux1)) &&
- !(GETF_LOOPBREAK(Ep) || GETF_LOOPCONT(Ep)) )
- {
- if (GETF_DEBUG(Ep)) printf(" [%2d|%d] CHECK %s\n",level, GETF_ABORTCOMMAND(Ep), arg);
- if (quoted)
- {
- if (GETF_DEBUG(Ep)) printf(" [%2d|%d] write %s\n",level, GETF_ABORTCOMMAND(Ep), arg);
- if (GETF_VIEWMODE(Ep) && !GETF_COMLINEMODE(Ep))
- {
- if (GETF_DEBUG(Ep)) printf("-- viewmode");
- goto fail;
- } /* if */
-
- if (GETF_ICONMODE(Ep))
- uniconify ();
-
- if ((ActualBlock.ep == Ep) && GETF_KILLBLOCK(Ep) && !GETF_COMLINEMODE(Ep))
- do_bdelete();
-
- text_write (arg);
- goto loop;
- } /* if (quoted) */
-
- if (isalpha (*arg) || (*arg == '_'))
- {
- low = 0;
- high = sizeof(Comm)/sizeof(Comm[0]) - 1;
-
- do
- {
- j = (low + high)/2;
-
- diff = stricmp (arg, Comm[j].name);
-
- if (!diff)
- break;
-
- if (diff < 0)
- high = j-1;
- else
- low = j+1;
- } while (low <= high);
-
- if (!diff)
- {
- if (GETF_DEBUG(Ep)) printf(" [%2d|%d] comm? %s\n",level, GETF_ABORTCOMMAND(Ep), arg);
-
- comm = &Comm[j];
-
- foundcmd = 1;
-
- av[0] = (UBYTE *)comm->name;
-
- for (j=1; j<=comm->args; j++)
- {
- av[j] = (UBYTE *)breakout (&str, "ed, &aux2);
-
- if (aux2)
- {
- if (repi == MAXIA)
- {
- free (aux2);
-
- DEFMESSAGE( _COM_too_many_Cargs_for, "command:\nToo many args for\n%s" )
- error (_COM_too_many_Cargs_for, av[0]);
-
- if (GETF_DEBUG(Ep)) printf("-- varargs Oflow");
-
- goto fail;
- } else
- {
- repstr[repi ++] = aux2;
- }
- }
-
- if (!av[j])
- {
- if (j < 2)
- DEFMESSAGE( _COM_bad_Cargument_of, "command:\nBad argument %ld of\n%s" )
- error (_COM_bad_Cargument_of, j, av[0]);
- else
- DEFMESSAGE( _COM_bad_Cargument_of_2, "command:\nBad argument %ld of\n%s %s ..." )
- error (_COM_bad_Cargument_of_2, j, av[0], av[1]);
-
- if (GETF_DEBUG(Ep)) printf("-- less args");
- goto fail;
- }
- } /* for all args */
-
- av[j] = NULL; /* end of arglist */
-
- process:
- if ((comm->flags & CF_COK) || !GETF_COMLINEMODE(Ep))
- {
- if (GETF_VIEWMODE(Ep) && !GETF_COMLINEMODE(Ep) && !(comm->flags & CF_VWM)) /* PATCH_NULL */
- {
- if (GETF_DEBUG(Ep)) printf("-- viewmode");
- goto fail; /* PATCH_NULL */
- } /* if */ /* PATCH_NULL */
-
- if (comm->flags & CF_PAR)
- {
- if (Partial)
- free (Partial);
-
- Partial = (char *)malloc (strlen (str) + 1);
- strcpy (Partial, str);
- str += strlen(str); /* skip string */
- } /* if CF_PAR */
-
- if (GETF_ICONMODE(Ep) && !(comm->flags & CF_ICO))
- {
- //printf ("* deiconify because off %s\n", av[0]);
- uniconify ();
- }
-
- if ((ActualBlock.ep == Ep) && GETF_KILLBLOCK(Ep) && !GETF_COMLINEMODE(Ep) && !(comm->flags & CF_BLK))
- do_bdelete();
-
- if (GETF_DEBUG(Ep)) printf (" [%2d|%d] comm: %s/%s\n", level, GETF_ABORTCOMMAND(Ep), av[0], av[1]);
-
- (*comm->func)(-1);
- } /* if CF_COK or Not Comlinemode */
-
- if (GETF_ABORTCOMMAND(Ep))
- {
- if (GETF_DEBUG(Ep)) printf("-- aborted");
- goto fail;
- }
-
- goto loop;
- } /* if arg == command */
- } else if (isdigit(*arg))
- {
- av[0] = "repeat";
- av[1] = arg;
- av[2] = (UBYTE *)breakout(&str, "ed, &aux2);
-
- if (aux2)
- {
- repstr[repi ++] = aux2;
- }
- if (GETF_DEBUG(Ep)) printf("-- repeat");
-
- if (!av[2])
- {
- DEFMESSAGE( _COM_bad_2nd_repeat_arg, "command:\nBad second argument\nfor short-repeat" )
- error (_COM_bad_2nd_repeat_arg);
- goto fail;
- }
-
- av[3] = 0;
- comm = &repcmd;
-
- goto process;
- } /* Repeat */
-
-
- #ifdef PATCH_ALIAS
- {
- /*
- ** Search for a macro - we had to put that scan
- ** before the checks for menus and keys, as
- ** keys are only checked up to 3 chars
- */
-
- void * macro;
- int ret;
-
- if (macro = (void*)getmacro(arg))
- {
- int narg = nummacroargs (macro);
-
- /* av[0] = (CHAR *)((NODE*)macro)->ln_Name; */
- if (GETF_DEBUG(Ep)) printf(" [%2d|%d] macro? %s\n",level, GETF_ABORTCOMMAND(Ep), arg);
-
- av[0] = NULL;
-
- foundcmd = 1;
-
- for (j = 1; j <= narg; ++j)
- {
- av[j] = (UBYTE *)breakout (&str, "ed, &aux2);
-
- if (aux2)
- {
- if (repi == MAXIA)
- {
- free(aux2);
- DEFMESSAGE( _COM_too_many_Margs_for, "macro:\nToo many args for\n%s" )
- error (_COM_too_many_Margs_for, av[0]);
- if (GETF_DEBUG(Ep)) printf("-- M:varargs Oflow");
- goto fail;
- } else
- {
- repstr[repi++] = aux2;
- }
- }
-
- if (!av[j])
- {
- DEFMESSAGE( _COM_bad_Margument_of, "macro:\nBad argument %ld of\n%s" )
- error (_COM_bad_Margument_of, j, av[0]);
- if (GETF_DEBUG(Ep)) printf("-- M:less args");
- goto fail;
- }
- }
-
- av[j] = NULL; /* end of arglist */
-
- if (GETF_DEBUG(Ep)) printf (" [%2d|%d] macro: %s/%s\n", level, GETF_ABORTCOMMAND(Ep), arg, av[1]);
- ret = callmacro(macro);
-
- if (!ret)
- {
- if (GETF_DEBUG(Ep)) printf("-- M:abort");
- goto fail;
- } /* if no succ */
-
- goto loop;
- } /* if */
- } /* block */
- #endif /* PATCH_ALIAS */
-
-
- /* Command not found, check for macro */
- {
- char * cmdstr;
- int ret;
-
- if ((cmdstr = keyspectomacro(arg)) || (cmdstr = menutomacro(arg)))
- {
- cmdstr = strdup (cmdstr);
-
- if (GETF_DEBUG(Ep)) printf (" [%2d|%d] key/menu %s\n", level, GETF_ABORTCOMMAND(Ep), cmdstr);
-
- ret = do_command (cmdstr);
-
- free (cmdstr);
-
- if (ret)
- {
- foundcmd = 1;
- goto loop;
- }
-
- if (GETF_DEBUG(Ep)) printf("-- K:abort");
-
- goto fail;
- } /* if arg is macro or menu */
- }
-
-
- /*
- *! PATCH_JUX (reine gaudi)
- *!
- *! Direct assignments of existing vars
- *! With that patch something is possible like:
- *! set abc 1 ... abc = 3 (instead of set abc 3)
- *!
- *! if arg1 is a "=" we search for a variable of the name in arg0
- *! if there is such a variable, we assign its value to the value
- *! in arg2 (the correct types are used)
- *!
- *! But what shall we do, if there was not such a variable???
- */
- {
- char * dummy = str;
- int type = VAR_NEX;
-
- while (*dummy && *dummy <33)
- {
- dummy ++;
- } /* while */
-
- if (*dummy == '=')
- {
- dummy ++;
-
- str = dummy;
-
- dummy = GetTypedVar (arg, &type);
-
- if (dummy)
- {
- free (dummy);
-
- dummy = breakout (&str, "ed, &aux2);
-
- if (!dummy)
- {
- DEFMESSAGE( _COM_assign_wo_value, "command:\nAssignment without value" )
- error (_COM_assign_wo_value);
- goto fail;
- } /* if */
-
- SetTypedVar (arg, dummy, type);
-
- if (aux2)
- {
- free (aux2);
- } /* if */
-
- goto loop;
- } else
- { /* there is no variable of the given name - WAS sollen wir jetzt machen ? einen Default verwenden ??? */
-
- } /* if */
- } /* if */
- } /* block direct assignment */
-
- /* Command still not found, check for public macro */
- /* code to be added */
-
- if (do_rxImplied (arg, str))
- DEFMESSAGE( _COM_unknown_command, "command:\nUnknown command\n`%s'" )
- error (_COM_unknown_command, arg);
-
- if (GETF_DEBUG(Ep)) printf("running into fail");
-
- fail:
- if (GETF_DEBUG(Ep)) printf ("fail[%2d|%d]\n", level, GETF_ABORTCOMMAND(Ep));
- --level;
-
- while (--repi >= 0)
- free (repstr[repi]);
-
- if (aux1) free (aux1);
-
- return(0);
-
- loop:
- if (aux1) free (aux1);
-
- // aux1 = NULL; /* PATCH_BREAK - is not necessary */
- } /* while (arg) */
-
- /* ret_ok: - point is not necessary */
- if (GETF_DEBUG(Ep)) printf ("ret1[%2d|%d]\n", level, GETF_ABORTCOMMAND(Ep));
-
- --level;
-
- while (--repi >= 0)
- free (repstr[repi]);
-
- // if (aux1) free (aux1); /* PATCH_BREAK - is not necessary */
-
- return(1);
- } /* do_command */
-
-
- /*DEFHELP #cmd misc NULL - no operation */
- /*DEFHELP #cmd misc NOP - no operation */
- /*DEFHELP #cmd misc REM com - add commend */
-
- DEFUSERCMD("nop", 0, CF_VWM|CF_ICO|CF_COK,void,do_null,(void),;)
- DEFUSERCMD("rem", 1, CF_VWM|CF_ICO|CF_COK,void,do_null,(void),;)
- DEFUSERCMD("null", 0, CF_VWM|CF_ICO|CF_COK,void,do_null,(void),)
- {
- } /* do_null */
-
-
- /*DEFHELP #cmd program,io SOURCE file - source a script file. '#' in first column for comment */
-
- DEFUSERCMD("source", 1, CF_VWM|CF_COK|CF_ICO, void, do_source, (long do_err),)
- {
- char buf[MAXLINELEN];
- FILE * fi;
- char * str;
- BPTR oldlock = CurrentDir(DupLock(Ep->dirlock));
-
- if (fi = fopen(av[1], "r"))
- {
- while (fgets(buf, MAXLINELEN, fi))
- {
- if (buf[0] == '#')
- continue;
- for (str = buf; *str; ++str)
- {
- if (*str == 9)
- *str = ' ';
- }
-
- if (str > buf && str[-1] == '\n')
- str[-1] = 0;
-
- do_command(buf);
-
- if (GETF_SOURCEBREAKS(Ep)) /* PATCH_NULL */
- {
- if (GETF_ABORTCOMMAND(Ep) || LoopBreak || LoopCont) /* PATCH_NULL */
- {
- break; /* PATCH_NULL */
- } /* if */ /* PATCH_NULL */
- } else /* PATCH_NULL */
- {
- SETF_ABORTCOMMAND(Ep,0); /* PATCH_NULL */
- LoopBreak = 0; /* PATCH_NULL */
- LoopCont = 0; /* PATCH_NULL */
- } /* if */ /* PATCH_NULL */
- }
- fclose(fi);
- } else
- {
- if (do_err)
- {
- DEFMESSAGE( __file_not_found, "%s:\nFile `%s'\nnot found" )
- error (__file_not_found, av[0], av[1]);
- }
- }
-
- UnLock(CurrentDir(oldlock));
- } /* do_source */
-
-
- /*DEFHELP #cmd win QUIT - close current window. If text was modified, a safety check is performed */
-
- DEFUSERCMD("quit", 0, CF_VWM|CF_ICO, void, do_quit, (void),)
- {
- SETF_QUITFLAG(Ep,1);
-
- ActivateWindow (Ep->win); /* HD damit aus AREXX */
- } /* do_quit */
-
-
- /*DEFHELP #cmd misc QUITALL - leave XDME. If any text was modified, a safety check is performed for that text */
-
- DEFUSERCMD("quitall", 0, CF_VWM|CF_ICO, void, do_quitall, (void),)
- {
- SETF_QUITFLAG(Ep,1);
- SETF_QUITALL(Ep,1);
-
- ActivateWindow (Ep->win); /* HD damit aus AREXX */
- } /* do_quitall */
-
-
- /*DEFHELP #cmd misc,io,program EXECUTE comm - Execute a CLI command. */
-
- DEFUSERCMD("execute", 1, CF_VWM|CF_ICO, void, do_execute, (void),)
- {
- BPTR oldlock = CurrentDir (Ep->dirlock);
- BPTR NilFH;
- PROC * proc = (PROC *)FindTask (NULL);
-
- NilFH = Open ("NIL:", 1006);
-
- if (NilFH)
- {
- void *oldConsoleTask = proc->pr_ConsoleTask;
-
- proc->pr_ConsoleTask = (APTR)BTOCP(NilFH, struct FileHandle *)->fh_Port;
-
- Execute (av[1], NilFH, NilFH);
-
- proc->pr_ConsoleTask = oldConsoleTask;
-
- Close(NilFH);
- } else
- {
- DEFMESSAGE( __nil_device_required, "%s:\nNIL:-device required" )
- error (__nil_device_required, av[0]);
- }
-
- CurrentDir(oldlock);
- } /* do_execute */
-
-
- /*
- * BREAKOUT()
- *
- * Break out the next argument. The argument is space delimited and
- * might be quoted with `' or (), or single quoted as 'c or )c
- *
- * Also: $var -variable insertion
- * ^c -control character
- */
-
- Prototype char * breakout (char ** ptr, char * quoted, char ** paux);
-
- char * breakout (char ** ptr, char * quoted, char ** paux)
- {
- char * str = *ptr;
- char * base;
- WORD count; /* Level of brace */
- char opc; /* Open-Char */
- char clc; /* Close-Char */
- char immode;
- char isaux;
- char buf[MAXLINELEN];
- WORD di, i;
-
- /* if (GETF_DEBUG(Ep)) printf("bout[ |%d] ? %s\n", GETF_ABORTCOMMAND(Ep), str); */
-
- count =
- opc =
- clc =
- immode=
- isaux =
- di = 0;
-
- *quoted = 0;
- if (paux)
- *paux = NULL;
-
- while (*str == ' ')
- ++str;
-
- if (!*str)
- return (NULL);
-
- *ptr = str;
- base = str;
-
- while (*str)
- {
- if (immode)
- {
- if (di != sizeof(buf)-1)
- buf[di++] = *str;
-
- str ++;
- continue;
- }
-
- if (count == 0)
- {
- if (*str == ' ')
- break;
-
- if (*str == '\'' || *str == ')')
- clc = *str;
- else if (*str == '`')
- {
- opc = '`';
- clc = '\'';
- } else if (*str == '(')
- {
- opc = '(';
- clc = ')';
- }
- }
-
- if (*str == opc)
- {
- count ++;
-
- if (str == *ptr)
- {
- *quoted = 1;
- base = ++ str;
- continue;
- }
- }
-
- if (*str == clc)
- {
- count --;
-
- if (count == 0 && *quoted) /* end of argument */
- break;
-
- if (str == *ptr && count < 0)
- {
- immode = 1;
- *quoted = 1;
- base = ++str;
-
- continue;
- }
- }
-
- /*
- * $varname $(varname) $`varname'. I.E. three forms are allowed,
- * which allows one to insert the string almost anywhere. The
- * first form names are limited to alpha-numerics, '-', and '_'.
- */
-
- if (*str == '$')
- {
- char * ptr2;
- char * tmpptr;
- char c,
- ce;
- WORD len;
-
- /* if (GETF_DEBUG(Ep)) printf("bout[ |%d] $ %s\n", GETF_ABORTCOMMAND(Ep), str); */
-
- ce = 0; /* first form */
- str ++; /* skip $ */
-
- if (*str == '(') /* second form */
- {
- ce = ')';
- ++str;
- } else if (*str == '`') /* third form */
- {
- ce = '\'';
- ++str;
- }
-
- ptr2 = str; /* start of varname */
-
- if (ce) /* until end char OR */
- {
- while (*ptr2 && *ptr2 != ce)
- ptr2 ++;
- } else /* smart end-varname */
- {
- while (isalnum(*ptr2) || *ptr2 == '-' || *ptr2 == '_' )
- {
- ptr2 ++;
- }
- }
-
- len = ptr2 - str; /* length of variable */
- c = *ptr2; *ptr2 = 0; /* temp. terminate \0 */
-
- /* if (GETF_DEBUG(Ep)) printf("bout[ |%d] var '%s'\n", GETF_ABORTCOMMAND(Ep), str); */
-
- if (stricmp(str, "path") == 0)
- {
- *ptr2 = c;
- isaux = 1;
-
- if (NameFromLock(Ep->dirlock, tmp_buffer, sizeof(tmp_buffer)))
- {
- i = strlen (tmp_buffer);
-
- if (di + i < sizeof(buf)-1)
- {
- strcpy (buf+di, tmp_buffer);
- di += i;
- }
- }
-
- str += len;
- if (ce)
- ++str;
-
- continue;
- } else
- if (stricmp(str, "file") == 0)
- {
- i = strlen(Ep->name);
- *ptr2 = c;
- isaux = 1;
- if (di + i < sizeof(buf)-1)
- {
- movmem(Ep->name, buf + di, i);
- di += i;
- buf[di] = 0;
- }
- str += len;
- if (ce)
- ++str;
- continue;
- #if 0 /* the following variables are part of SPC.PRE */
- } else
- if (stricmp(str, "currentdir") == 0)
- {
- *ptr2 = c;
- isaux = 1;
-
- if (NameFromLock (Ep->dirlock, tmp_buffer, sizeof(tmp_buffer)))
- {
- i = strlen(tmp_buffer);
-
- if (di + i < sizeof(buf)-1)
- {
- strcpy (buf + di, tmp_buffer);
- di += i;
- }
- }
-
- str += len;
-
- if (ce)
- ++str;
-
- continue;
- } else
- if (stricmp(str, "filename") == 0)
- {
- *ptr2 = c;
- isaux = 1;
-
- if (NameFromLock(Ep->dirlock, tmp_buffer, sizeof(tmp_buffer)))
- {
- if (AddPart (tmp_buffer, Ep->name, sizeof(tmp_buffer)))
- {
- i = strlen (tmp_buffer);
-
- if (di + i < sizeof(buf)-1)
- {
- strcpy(buf + di, tmp_buffer);
- di += i;
- }
- }
- }
-
- str += len;
- if (ce)
- ++str;
- continue;
- } else if (!stricmp(str, "rexxport")) /* TJM */
- {
- *ptr2 = c;
- isaux = 1;
-
- if (di + strlen(RexxPortName) < sizeof(buf)-1)
- {
- strcpy(buf + di, RexxPortName);
- di += strlen(buf + di);
- }
-
- str += len;
-
- if (ce)
- ++str;
- continue;
- } else if (!stricmp(str, "rxresult"))
- {
- *ptr2 = c;
- isaux = 1;
-
- if (di + strlen(get_rexx_result()) < sizeof(buf)-1)
- {
- strcpy(buf + di, get_rexx_result());
- di += strlen(buf + di);
- }
-
- str += len;
-
- if (ce)
- ++str;
- continue;
- #endif
- } else if (tmpptr = getvar(str))
- {
- ptr2 = tmpptr;
- str[len] = c;
- isaux = 1;
-
- if (di + strlen(ptr2) < sizeof(buf)-1)
- {
- strcpy(buf + di, ptr2);
- di += strlen(buf + di);
- }
-
- str += len;
-
- if (ce)
- ++str;
-
- free(ptr2);
- continue;
- }
-
- *ptr2 = c;
- str --;
-
- if (ce)
- str --;
- } else if (*str == '^' && (str[1] & 0x1F)) /* CTRL-sequence */
- {
- str ++;
- *str &= 0x1F;
- isaux = 1;
- } else if (*str == '\\' && str[1])
- {
- /* reverted to old code */
- #ifdef NOTDEF
- if (!count) /* ignore \ */
- {
- str ++;
- } else if (*quoted && count == 1) /* remove it, but check next char */
- {
- #endif
- str ++;
- #ifdef NOTDEF
- isaux = 1;
- continue;
- } else /* don't remove it, but also ignore next char */
- {
- buf[di ++] = *str ++;
- }
- #endif
- isaux = 1;
- }
-
- buf[di ++] = *str ++;
- } /* while (*str) */
-
- buf[di ++] = 0;
-
- if (isaux)
- {
- *paux = malloc (di);
- strcpy (*paux, buf);
- base = *paux;
- }
-
- if (*str) /* space ended */
- {
- *str = '\0';
- *ptr = str + 1; /* next arg */
- } else
- {
- *ptr = str; /* last arg */
- }
-
- return (base);
- } /* breakout */
-
-
- /******************************************************************************
- ***** ENDE command.c
- ******************************************************************************/
-
- /*DEFHELP #cmd special BREAKOUT - Some words about Variable Expansion */
- /*DEFLONG #long BREAKOUT
-
- It seems that some words must be said to variable expansion ...
- the bad thing is, I have not written the function, that's doing the
- expansion, so i cannot guarantee, that the following text is absolutely
- correct ...
-
- The current Version of XDME's macro interpreter expands variables in
- preparation of command calls; furthermore, the macro language does not
- know anything else than commands ... (ok, there are other things
- than only commands: abbreviated commands (quoted text for write,
- and numbers for repeat ...), macros (which are treated like commands)
- and ARexx, but these themes are not discussed here ...)
- even "constructs" like IF, WHILE, REPEAT are commands, and so they
- have also arguments ... and there is no difference in the evaluation
- of their arguments compared to other commands ...
-
- (in the following section we precede ecah example line with "%"
- and we use a non-existing command called "out", so the following
- 2 macrodefinitions are useful when testing the examples ...
- the first one just ignores the leading "%" and the second displays
- its argument in the next line; the mapping one lets XDME
- send the current line to its macro interpreter)
- % setmacro % 0 ()
- % setmacro out 1 (firstnb down insline tab (-> \$arg1) title OK)
- % map a-a (eval \$currentline)
-
- let us suppose we had done the following variable assignments ...
- % set alpha xx
- % set cmp[1] Amiga
- % set cmp[2] Atari
- % set cmp[3] Clone
- % set best 1
- % set quality best
-
- * A Variable name may contain only alphanumeric chars and/or "-", "_"
- if You wanna use other charcters inside a variablename, it must be
- enclosed with parantheses or Single Quotation marks ( "(...)" or
- "`...'" both ways are called 'quotes' in the next paragraphes).
-
- * The Interpreter currently has knowledge of something like 4 classes
- of characters, that are alphanumeric chars together with "-" and "_"
- which make up continous blocks of text, whitespace (for XDME this is
- always SPACE (0x20), since TAB (0x07) ist translated to 0x20 when
- reading files ...) Special characters ( "\\", "(", ")", "`", "'" and
- "$" ) and all other chracters;
- as long as no special character is invloved, we can say Whitespace
- is used as delimiter for arguments;
-
- % out ah.that/is*very;interesting
- -> ah.that/is*very;interesting
-
- as soon as special charcters are involved the situation gets hairy ...
- - "\\" are ignored, instead the nex caracter looses all of its meanings
- and is just copied to the current argument ('escaping')
- so we can say
-
- % out now\\ we\\ build\\ a\\ long\\ string\\ \\w/\\ whitespace\\ and\\ "\\$x"
- -> now we build a long string w/ whitespace and "$x"
-
- in order to get a "\\", that caharcter must actually be doubled
-
- % out \\\\
- -> \\
-
- - "$" introduces the next variable; as stated above, a variable
- name may contain only alphanumeric chars and/or "-", "_", else
- it must be enclosed w/ quotes
-
- % out $quality
- -> best
- % out $(cmp[1])
- -> Amiga
- % out $cmp[1]
- -> $cmp[1]
- (assuming 'cmp' in an unset variable))
-
- lonely "$" or sequences of "$" like "$$" will probably disturb the
- variable expansion, (try to expand a variable of no name) so the
- following macro might break ("might" since this behaviour might be
- changed one day)...
-
- % out $$
- (probably no output ...)
-
- - "(" and ")" as well as "`" and "'" can disable the whitespace
- argument splitting ... ( "quoting" )
-
- % out (hey, now w/out espaces)
- -> hey, now w/out espaces
-
- these quotes can also be stacked, but inside of "(/)" "`/'" will
- loose their meaning and vice versa
-
- % eval (out ( hello ( hahah ) ` )) out ( ' hohoho )
- -> hello ( hahah ) `
- -> ' hohoho
-
- if a open-quote has no conterpart, it quotes the complete rest of the
- current string
-
- % out ( sim sala
- -> sim sala
-
- if an close-quote has no counter part, the same as above;
- the tricky thing is: a leading close quote cannot have a
- matching open-quote
-
- % out ) now we can type whatever we want ... ( ` ' ' )
- -> now we can type whatever we want ... ( ` ' ' )
-
- * If a variable is unknown to the system, or it cannot be resoved due
- to other reasons, e.g. to low memory conditions, it is expanded to
- itself; additionally it may happen, that the variable Module also
- sets the abortflag (this behaviour it currently not defined, so
- it might depend on the variablename being used)
-
- * You can ask, if a variable exists by preceeding its name with a
- questionmark ( "?" )
- so in the above example we could call
- % out $(?alpha)
- -> 1
- (we need quotes, since a questionmark is else treated
- as a breaking (non-alnum) character ...)
-
- * if You want to expand nested variables, You must reinvoke the
- interpreter; for that purpose, You can use the command EVAL;
- please note, that - as stated above - also IF and WHILE
- are commands; for that resaon, it might be neccessary to put
- a lot of esacpes in highly nested macros ...
-
- % out ( the $(cmp[$$quality]) is the $quality )
- -> the $(cmp[$best]) is the best
- (probably no output, see above ...)
-
- % eval (out ( the \$(cmp[\$$quality]) is the $quality ))
- -> the $(cmp[1]) is the best
-
- % eval (eval (out ( the \\\$(cmp[\$$quality]) is the $quality )))
- -> the Amiga is the best
-
-
- Additional comment: when using AmigaGuide (v34) the above text
- may have many duplicated backslashes; this is caused by the
- fact that Multiview (v39f) does treat the backslash as a
- special character, so I had the choose between using single
- backslashes for AmigaGuide v34 which then are invisible for
- Mulitiview, or using them duplicated for v34 what is the right
- way for Multiview ...
-
- */
-